package com.sunyard.pcc.shiro.core;

import com.sunyard.pcc.common.bo.SysUserLoginLimitBO;
import com.sunyard.pcc.common.constant.ErrorCodeEnum;
import com.sunyard.pcc.common.exception.PccCommonException;
import com.sunyard.pcc.core.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: Hewei
 * @Description: 自定义的密码比较器, 限制用户五分钟内不能错误登录4次以上
 * @Date: Created in 17:31 2018/2/8
 */
@Slf4j
@Component
public class LoginLimitCredentialsMatcher extends HashedCredentialsMatcher {

    private static final int FAILCOUNT = 5;

    @Autowired
    private UserService userService;

    @Value(value = "${sunyard.redis.open}")
    private Boolean useRedis;

    @Value(value = "${sunyard.login.redis}")
    private Boolean saveLoginInRedis;


    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //获取用户名
        String username = (String) token.getPrincipal();

        //用户登陆次数验证
        try {
            userService.LoginLimitByConfig(username, useRedis, saveLoginInRedis);
        } catch (PccCommonException e) {
            log.info("", e);
            switch (ErrorCodeEnum.getEnumByCode(e.getCode())) {
                //登录错误次数超出限制
                case LOGIN_COUNT_LIMIT_ERROR:
                    throw new ExcessiveAttemptsException();
                case USER_IS_DISABLED:
                    throw new DisabledAccountException();
                case USER_DO_NOT_EXITS:
                    throw new UnknownAccountException();
                default:
                    throw new AuthenticationException();
            }
        }


        Boolean matches = super.doCredentialsMatch(token, info);

        if (matches) {
            try {
                userService.resetFailureNum(username, useRedis, saveLoginInRedis);
            } catch (PccCommonException e) {
                log.info("", e);
                throw new AuthenticationException();
            }
        }

        return matches;
    }

}
